#ifndef INC_BUF_H
#define INC_BUF_H

#include <stdint.h>
#include "sleeplock.h"
#include "fs.h"

#include "list.h"
#include "mpsc.h"

#define BSIZE   512

#define B_VALID 0x2     /* Buffer has been read from disk. */
#define B_DIRTY 0x4     /* Buffer needs to be written to disk. */

struct buf {
    mpsc_node_t node;
    list_node_t bnode;

    volatile int started;
    int flags;
    uint32_t dev;
    uint32_t blockno;
    uint32_t refcnt;
    uint8_t data[BSIZE];
    struct sleeplock lock;
};

#define GET_BUF(bnode) \
    ((struct buf *)((char *)(bnode) - sizeof(mpsc_node_t)))

typedef struct {
    // return 1 on success
    int (*sync)(struct buf *);
} virtio_i;

extern virtio_i virtio;

void        binit();
int         bwrite(struct buf *b);
void        brelse(struct buf *b);
struct buf *bread(uint32_t dev, uint32_t blockno);

void b_pin(struct buf *b);
void b_unpin(struct buf *b);
void b_invalidate();
void b_full_reset();

#endif
